﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml;

namespace ProjectFinal {
	public class Patron : INotifyPropertyChanged {
		public event PropertyChangedEventHandler PropertyChanged;
		private void NotifyPropertyChanged(string name) {
			if(PropertyChanged != null)
				PropertyChanged(this, new PropertyChangedEventArgs(name));
		}
	
		private int patronID;		//Patron ID#
		public int ID {
			get { return patronID; }
		}

		private String name;		//Patron Name
		public string Name {
			get { return name; }
			set { name = (value == null || value.Trim().Equals("")) ? name : value.Trim(); } // Don't allow a blank name
		}

		private Boolean adult;		//is Patron and adult?
		public bool Adult {
			get { return adult; }
		}

		List<String> items = new List<String>();	//List of all the Item ID Codes Patron has

		int MAXITEMS;							//Maximum number of items the Patron can check out
		public int getMaxItems() { return MAXITEMS; }

		int	LOANTIME_ADULT_BOOK,	//Checkout time limits
				LOANTIME_CHILD_BOOK,
				LOANTIME_DVD,
				LOANTIME_VHS;

		//True if patron has something checked out
		public bool HasItems {
			get { return items.Count > 0; }
		}

		//Create a Patron
		//Param:	Name, ID#, Adult status
		public Patron(String name, int ID, Boolean adult) {
			this.name = name;
			this.patronID = ID;
			this.adult = adult;
			if(adult == true)
				MAXITEMS = Constants.ADULT_MAX;
			else
				MAXITEMS = Constants.CHILD_MAX;
			LOANTIME_ADULT_BOOK = Constants.LOANTIME_ADULT_BOOK;
			LOANTIME_CHILD_BOOK = Constants.LOANTIME_CHILD_BOOK;
			LOANTIME_DVD = Constants.LOANTIME_DVD;
			LOANTIME_VHS = Constants.LOANTIME_VHS;
		}//Patron(string, int, bool)

		//Create a Patron based on data in an XML node
		//Param:	node in which to find data
		public Patron(XmlNode node) {
			this.adult = node.Attributes["a"].Value.Equals("True");
			this.patronID = Int32.Parse(node.Attributes["id"].Value);
			this.name = node.InnerText;
			foreach(XmlNode n in node.ChildNodes)
				if(n.Name == "book" || n.Name == "media")
					this.items.Add(n.Attributes["id"].Value);

			if(this.adult)
				MAXITEMS = Constants.ADULT_MAX;
			else
				MAXITEMS = Constants.CHILD_MAX;
			LOANTIME_ADULT_BOOK = Constants.LOANTIME_ADULT_BOOK;
			LOANTIME_CHILD_BOOK = Constants.LOANTIME_CHILD_BOOK;
			LOANTIME_DVD = Constants.LOANTIME_DVD;
			LOANTIME_VHS = Constants.LOANTIME_VHS;
		}//Patron(XmlNode)

		//Check out an Item to this patron
		//Param:	Item to check out, today's date
		//Post:		Item is checked out.
		//				returns True if item is checked out, false otherwise
		public Boolean checkOutItem(Item i, Date today) {
			if(items.Count < MAXITEMS) {
				int time;
				if(i.getType() == MediaType.adultBook)
					time = LOANTIME_ADULT_BOOK;
				else if(i.getType() == MediaType.childBook)
					time = LOANTIME_CHILD_BOOK;
				else if(i.getType() == MediaType.DVD)
					time = LOANTIME_DVD;
				else //if(i.getType() == MediaType.Video)
					time = LOANTIME_VHS;

				if(i.checkOut(patronID, today + time)) { //is the book available for check out?
					items.Add(i.ID);
					return true; //yes it was
				} else
					return false;//no it was not
			} else
				return false;//at MAXITEMS
		}//bool checkOutItem(Iten, Date)

		//Check in Item
		//Param:	Item to check in
		//Post:		Item is checked in.
		//				Returns true if Patron has Item and it is successfully turned in, false otherwise
		public Boolean checkInItem(Item i) {
			if(items.Contains(i.ID)) {
				i.checkIn();
				items.RemoveAt(items.IndexOf(i.ID));
				return true;
			} else
				return false;
		}//bool checkInItem(Item)

		//Return number of items this Patron has checked out
		public int totalItems() { return items.Count; }
		
		//Get list of Items this Patron has checked out
		public List<String> getItems() { return items; }

		//Append patron data to an XML Node
		//Param:	XML Document, XML Node to populate
		//Post:		returns XML Node reflecting the appendations (is that a word?)
		//Note:		if node already contains data, it is NOT removed.  New data are appended.
		public XmlNode writeThyself(XmlDocument xmlDoc, XmlNode node) {
			XmlAttribute attrID = xmlDoc.CreateAttribute("id");		//ID#
			attrID.Value = this.patronID.ToString();
			node.Attributes.Append(attrID);
			XmlAttribute attrAdult = xmlDoc.CreateAttribute("a");	//Is adult?
			attrAdult.Value = this.adult.ToString();
			node.Attributes.Append(attrAdult);
			node.InnerText = this.name;
			foreach(string i in items) {//Add reference to every Item this Patron has
				XmlNode itemNode;
				if(BusinessRules.getSpecificItem(i).getType() == MediaType.adultBook ||
						BusinessRules.getSpecificItem(i).getType() == MediaType.childBook)
					itemNode = xmlDoc.CreateElement("book");
				else
					itemNode = xmlDoc.CreateElement("media");
				XmlAttribute attrIID = xmlDoc.CreateAttribute("id");
				attrIID.Value = i;
				itemNode.Attributes.Append(attrIID);
				node.AppendChild(itemNode);
			}
			return node;
		}//void writeThyself(XmlDocument, XmlNode)
	}//class Patron
}//namespace
